#pragma once 
#include <pthread.h>
#include <iostream>
#include <queue>
#include <unistd.h>


using namespace std;

template<class T>
class BlockQueue
{
  static const int defaultnum = 5;
public:
  BlockQueue(int maxcap = defaultnum)
    :maxcap_(maxcap)
  {
    pthread_mutex_init(&mutex_,nullptr);
    pthread_cond_init(&c_cond_,nullptr);
    pthread_cond_init(&p_cond_,nullptr);
    low_water_=maxcap_/3;
    high_water_=maxcap_*2/3;
  }

  T pop() //消费者
  {
    pthread_mutex_lock(&mutex_);
    while(q_.empty()) //用while循环的原因是防止伪唤醒
    {
      //队列为空,等待
      pthread_cond_wait(&c_cond_,&mutex_);
    }
    T out = q_.front();
    q_.pop();

    pthread_cond_signal(&p_cond);
    pthread_mutex_unlock(&mutex_);
    return out;
  }

  void push(const T& in) //生产者 
  {
    pthread_mutex_lock(&mutex_);
    while(q_.size() == maxcap_) //用while循环的原因是防止伪唤醒
    {
      //队列已满,等待
      pthread_cond_wait(&p_cond_,&mutex_);
    }
    q_.push(in);

    //if(q_.size() > high_water_)pthread_cond_signal(&c_cond_);
    pthread_cond_signal(&c_cond);
    pthread_mutex_unlock(&mutex_);
  }

  ~BlockQueue()
  {
    pthread_mutex_destroy(&mutex_);
    pthread_cond_destroy(&c_cond_);
    pthread_cond_destroy(&p_cond_);
  }

private:
  queue<T> q_; //共享资源
  int maxcap_; //极值
  pthread_mutex_t mutex_;
  pthread_cond_t c_cond_;
  pthread_cond_t p_cond_;
  int low_water_;
  int high_water_;
};